#include <behaviortree_cpp_v3/behavior_tree.h>
#include <behaviortree_cpp_v3/bt_factory.h>
using namespace std;

class SaySomething : public BT::SyncActionNode
{
public:
    SaySomething(const string& name, const BT::NodeConfiguration& config)
        : BT::SyncActionNode(name, config)
    {
    }

    BT::NodeStatus tick() override
    {
        auto message = getInput<string>("message");
        if (!message)
        {
            return BT::NodeStatus::FAILURE;
        }

        cout << this->name() << ":" << message.value() << endl;
        return BT::NodeStatus::SUCCESS;
    }

    static BT::PortsList providedPorts()
    {
        return { BT::InputPort<string>("message") };
    }
};

BT::NodeStatus SaySomethingSimple(BT::TreeNode& tree)
{
    auto msg = tree.getInput<string>("message");
    if (!msg)
    {
        printf("Error: missing input [message]\n");
        return BT::NodeStatus::FAILURE;
    }
    printf("SaySomethingSimple: %s\n", msg.value().c_str());
    return BT::NodeStatus::SUCCESS;
}

class ThinkWhatToSay : public BT::SyncActionNode
{
public:
    ThinkWhatToSay(const string& name, const BT::NodeConfiguration& config)
        : BT::SyncActionNode(name, config)
    {
    }

    BT::NodeStatus tick() override
    {
        setOutput<string>("text", "the answer is 42");
        return BT::NodeStatus::SUCCESS;
    }

    static BT::PortsList providedPorts()
    {
        return { BT::OutputPort<string>("text") };
    }
};

static const char* xml_text = R"(

 <root main_tree_to_execute = "MainTree" >

     <BehaviorTree ID="MainTree">
        <Sequence name="root">
            <SaySomething     message="hello" />
            <SaySomethingSimple    message="this works too" />
            <ThinkWhatToSay   text="{the_answer}"/>
            <SaySomethingSimple    message="{the_answer}" />
        </Sequence>
     </BehaviorTree>

 </root>
 )";

int main()
{
    BT::BehaviorTreeFactory factory;
    // 注册节点
    factory.registerNodeType<SaySomething>("SaySomething");
    factory.registerNodeType<ThinkWhatToSay>("ThinkWhatToSay");

    // 注册一个简单: 函数节点
    BT::PortsList say_something_ports = { BT::InputPort<string>("message") };
    factory.registerSimpleAction("SaySomethingSimple", SaySomethingSimple, say_something_ports);

    auto tree = factory.createTreeFromText(xml_text);
    tree.tickRootWhileRunning();

    return 0;
}